﻿using Newtonsoft.Json;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

namespace HobSoft.SoccerBet2014.Domain.Common.BfApi
{
    [JsonObject()]
    public class ApiJsonRpcContent : HttpContent
    {
        protected const int DEF_REQUEST_ID = 1;
        protected const string DEF_JSON_RPC = "2.0";
        public ApiJsonRpcContent(int id, string jsonRpc, string method, object paramters)
        {
            ID = id;
            JsonRpc = jsonRpc;
            Method = method;
            Params = paramters;
            Headers.Add("content-type", "application/json");
            Encoding = System.Text.Encoding.UTF8;
        }

        public ApiJsonRpcContent(string method, object paramters)
            : this(DEF_REQUEST_ID, DEF_JSON_RPC, method, paramters)
        {

        }

        public ApiJsonRpcContent()
        {
            ID = DEF_REQUEST_ID;
            JsonRpc = DEF_JSON_RPC;
            Headers.Add("content-type", "application/json");
            Encoding = System.Text.Encoding.UTF8;
        }

        [JsonProperty("id")]
        public int ID
        {
            get;
            protected set;
        }

        [JsonProperty("method")]
        public string Method
        {
            get;
            set;
        }

        [JsonProperty("jsonrpc")]
        public string JsonRpc
        {
            get;
            protected set;
        }

        [JsonProperty("params")]
        public object Params
        {
            get;
            set;
        }

        [JsonIgnore]
        public System.Text.Encoding Encoding { get; set; }

        [JsonIgnore]
        protected int BufferLength { get; set; }
        [JsonIgnore]
        protected byte[] SerializeJsonBuffer { get; set; }

        protected byte[] SerializeThisToJson()
        {
            var json = JsonConvert.SerializeObject(this, Formatting.Indented, new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                ContractResolver = new ExcludePropertiesContractResolver(new string[] { "Headers" })
            });
            SerializeJsonBuffer = Encoding.GetBytes(json);
            BufferLength = SerializeJsonBuffer.Length;
            return SerializeJsonBuffer;
        }

        protected override Task<Stream> CreateContentReadStreamAsync()
        {
            if (BufferLength == 0)
                SerializeThisToJson();
            return Task.FromResult<Stream>(new MemoryStream(SerializeJsonBuffer, 0, BufferLength, false, false));
        }

        protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
        {
            if (BufferLength == 0)
                SerializeThisToJson();
            return Task.Factory.FromAsync<byte[], int, int>(
                          new Func<byte[], int, int, AsyncCallback, object, IAsyncResult>(stream.BeginWrite)
                        , new Action<IAsyncResult>(stream.EndWrite), SerializeJsonBuffer, 0, BufferLength, null);
        }

        protected override bool TryComputeLength(out long length)
        {
            if (BufferLength == 0)
                SerializeThisToJson();
            length = BufferLength;
            return true;
        }
    }
}
